import path from 'path'
import fs from 'fs'
import axios from 'axios'
import iconv from 'iconv-lite'
import ProgressBar from 'progress'

import puppeteer, { Browser, Page } from 'puppeteer'
let browser: Browser
let browserPage: Page

/** 获取扩展名 */
export function getExtName(filename: string) {
  return path.extname(filename)?.replace('.', '')
}

/** 获取文件名称，无扩展名 */
export function getBaseName(filename: string) {
  let basename = path.basename(filename) || ''
  let extname = path.extname(filename) || ''
  return basename.replace(extname, '')
}

/** 获取对象的字段值 */
export function getObjectValue<T extends object, K extends keyof T>(obj: T, key: K) {
  return obj[key]
}

/**
 * 删除指定文件夹下的所有文件
 * 
 * @param path 文件夹路径
 */
export function deleteDir(path: string) {
  return new Promise<void>((resolve, reject) => {
    let files = []
    if (fs.existsSync(path)) {
      files = fs.readdirSync(path)
      for (let file of files) {
        let curPath = path + "/" + file
        if (fs.statSync(curPath).isDirectory()) {
          deleteDir(curPath)
        } else {
          fs.unlinkSync(curPath)
        }
      }
      fs.rmdirSync(path)
    }
    resolve()
  })
}

/** 
 * 获取指定范围内的随机数
 * 
 * 返回 [x, y] 范围内的随机数
 */
export function getRamdomNumberByRange(x: number, y: number) {
  return Math.round(Math.random() * (y - x) + x)
}

/** 
 * 获取html字符串
 */
export async function getHtml(url: string) {
  const res = await axios.get(url)
  return res.data
}

/** 
 * 使用无头浏览器获取html
 */
export async function getHtmlByBrower(url: string) {

  if (!browser) {
    browser = await puppeteer.launch({ headless: 'new' })
  }
  if (!browserPage) {
    browserPage = await browser?.newPage()
  }

  // 跳转列表页
  await browserPage.goto(url)
  let pageContent = await browserPage.content()

  return pageContent

}

/** 
 * 获取重新编码后的html字符串
 */
export async function getRecodeHtml(url: string, originCode: string, targetCode: string) {
  const res = await axios.get(url, { responseType: 'arraybuffer' })
  let decodeStr = iconv.decode(Buffer.from(res.data), originCode)
  let htmlStr = iconv.encode(decodeStr, targetCode).toString()
  return htmlStr
}

/** 
 * 下载图片
 */
export async function downloadImg(url: string, savePath: string = './') {

  const { data, headers } = await axios.get(url, { responseType: 'stream' })

  const totalLength = headers['content-length']

  let progressStr = `-> ${path.basename(savePath)} [:bar] :percent :etas`

  const progressBar = new ProgressBar(progressStr, {
    width: 40,
    complete: '=',
    incomplete: ' ',
    renderThrottle: 1,
    total: parseInt(totalLength)
  })

  const writer = fs.createWriteStream(savePath)
  data.on('data', (chunk: Buffer) => progressBar.tick(chunk.length))
  data.pipe(writer)

  await new Promise<void>((resolve, reject) => {
    writer.on('finish', () => {
      resolve()
    })
    writer.on('error', reject)
  })

}